Add find_domain_rcu_lock() and domain_rcu_unlock().
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 21 Feb 2007 16:33:34 +0000 (16:33 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 21 Feb 2007 16:33:34 +0000 (16:33 +0000)
Signed-off-by: Jose Renato Santos <jsantos@hpl.hp.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/common/domain.c
xen/include/xen/sched.h

index b9115250062cb7621d6060916c02c15d4872cbfe..d1ea9a214893e71f261149b883dcadfd32b3e365 100644 (file)
@@ -217,8 +217,10 @@ struct domain *get_domain_by_id(domid_t dom)
     struct domain *d;
 
     rcu_read_lock(&domlist_read_lock);
-    d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]);
-    while ( d != NULL )
+
+    for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]);
+          d != NULL;
+          d = rcu_dereference(d->next_in_hashbucket) )
     {
         if ( d->domain_id == dom )
         {
@@ -226,14 +228,34 @@ struct domain *get_domain_by_id(domid_t dom)
                 d = NULL;
             break;
         }
-        d = rcu_dereference(d->next_in_hashbucket);
     }
+
     rcu_read_unlock(&domlist_read_lock);
 
     return d;
 }
 
 
+struct domain *find_domain_rcu_lock(domid_t dom)
+{
+    struct domain *d;
+
+    rcu_read_lock(&domlist_read_lock);
+
+    for ( d = rcu_dereference(domain_hash[DOMAIN_HASH(dom)]);
+          d != NULL;
+          d = rcu_dereference(d->next_in_hashbucket) )
+    {
+        if ( d->domain_id == dom )
+            return d;
+    }
+
+    rcu_read_unlock(&domlist_read_lock);
+
+    return NULL;
+}
+
+
 void domain_kill(struct domain *d)
 {
     domain_pause(d);
index a371c36de02c9305aa13eacfc78c6fda94456d42..61d228a8a6d7539066fb55310fa08da813a2d3ec 100644 (file)
@@ -269,6 +269,21 @@ int construct_dom0(
     unsigned long initrd_start, unsigned long initrd_len,
     char *cmdline);
 
+/*
+ * find_domain_rcu_lock() is more efficient than get_domain_by_id().
+ * This is the preferred function if the returned domain reference
+ * is short lived,  but it cannot be used if the domain reference needs 
+ * to be kept beyond the current scope (e.g., across a softirq).
+ * The returned domain reference must be discarded using domain_rcu_unlock().
+ */
+struct domain *find_domain_rcu_lock(domid_t dom);
+
+/* Finish a RCU critical region started by find_domain_rcu_lock(). */
+static inline void domain_rcu_unlock(struct domain *d)
+{
+    rcu_read_unlock(&domlist_read_lock);
+}
+
 struct domain *get_domain_by_id(domid_t dom);
 void domain_destroy(struct domain *d);
 void domain_kill(struct domain *d);